package tool

import (
	"context"
	"encoding/json"
	"fmt"
	"lsgfish/server/internal/config"
	"lsgfish/server/internal/model"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/redis/go-redis/v9"
)

var (
	RDB              *redis.Client
	Ctx              = context.Background()
	RedisServiceTool RedisService
)

// 初始化redis
func InitRedis() error {
	RDB = redis.NewClient(&redis.Options{
		Addr: fmt.Sprintf("%v:%v",
			config.Conf.Redis.Protocol,
			config.Conf.Redis.Port,
		),
		Password: config.Conf.Redis.Password,
		DB:       config.Conf.Redis.DB,
	})

	// 测试连接
	if err := RDB.Ping(Ctx).Err(); err != nil {
		return fmt.Errorf("连接Redis失败: %w", err)
	}

	RedisServiceTool = NewRedisService()
	return nil
}

type RedisService interface {
	//从请求头中获取token，根据token获取用户信息
	GetToken(c *gin.Context) (model.User, error)
	// 设置token
	SetToken(token string, user model.User) error
	// 删除token
	DeleteToken(token string) error
	// 获取验证码
	//
	// email: 存储时的邮箱
	//
	// prefix: 存储时的前缀
	GetCode(email string, prefix string) (string, error)
	// redis存储验证码
	//
	// email: 存储时的邮箱
	//
	// prefix: 存储时的前缀
	SetCode(email, code string, prefix string, expiration time.Duration) error
	// DeleteCode 删除redis存储的验证码
	//
	// email: 存储时的邮箱
	//
	// prefix: 存储时的前缀
	DeleteCode(email string, prefix string) error
}

// token在Redis中的key前缀
const (
	// token在Redis中的key前缀
	TokenKeyPrefix = "token:"
	// 注册验证码 在Redis中的key前缀
	RegisterVerifyCodePrefix = "register:"
	// 验证码登录 在Redis中的key前缀
	LoginVerifyCodePrefix = "login:"
)

// TokenService Redis令牌服务结构体
type TokenService struct {
	rdb *redis.Client
	ctx context.Context
}

// NewTokenService 创建新的TokenService实例
func NewRedisService() RedisService {
	return &TokenService{
		rdb: RDB,
		ctx: Ctx,
	}
}

// GetToken 根据token获取用户信息
func (s *TokenService) GetToken(c *gin.Context) (model.User, error) {
	var user model.User
	token := c.GetHeader("Authorization")
	val, err := s.rdb.Get(s.ctx, TokenKeyPrefix+token).Result()
	if err != nil {
		return user, err
	}

	if err := json.Unmarshal([]byte(val), &user); err != nil {
		return user, err
	}

	return user, nil
}

// SetToken 设置用户token
func (s *TokenService) SetToken(token string, user model.User) error {
	jsonUser, err := json.Marshal(user)
	if err != nil {
		return err
	}

	return s.rdb.Set(s.ctx, TokenKeyPrefix+token, jsonUser, time.Hour*time.Duration(config.Conf.Token.Expire)).Err()
}

// DeleteToken 删除用户token
func (s *TokenService) DeleteToken(token string) error {
	return s.rdb.Del(s.ctx, TokenKeyPrefix+token).Err()
}

// GetCode 获取验证码
func (s *TokenService) GetCode(email string, prefix string) (string, error) {
	code, err := s.rdb.Get(s.ctx, prefix+email).Result()
	if err != nil && err == redis.Nil {
		return "", nil
	}
	return code, err
}

// SetCode 设置验证码
func (s *TokenService) SetCode(email, code string, prefix string, expiration time.Duration) error {
	return s.rdb.Set(s.ctx, prefix+email, code, expiration).Err()
}

// DeleteCode 删除验证码
func (s *TokenService) DeleteCode(email string, prefix string) error {
	return s.rdb.Del(s.ctx, prefix+email).Err()
}
